#region Header
//************************************************************************************
// Name: NHibernateSessionModule
// Description: NHibernateSessionModule
// Created On:  02-Aug-2011
// Created By:  Swathi
// Last Modified On:
// Last Modified By:
// Last Modified Reason:
//*************************************************************************************
#endregion Header
using System;
using System.Configuration;
using System.IO;
using System.Web;
using Base.Utils;
using Base.Data;

namespace Base.Data
{
    /// <summary>
    /// Implements the Open-Session-In-View pattern using <see cref="NHibernateSessionManager" />.
    /// Inspiration for this class came from Ed Courtenay at 
    /// http://sourceforge.net/forum/message.php?msg_id=2847509.
    /// </summary>
    public class NHibernateSessionModule : IHttpModule
    {
        #region IHttpModule Members

        public void Init(HttpApplication context)
        {
            context.BeginRequest += BeginTransaction;
            context.EndRequest += CommitAndCloseSession;
        }

        public void Dispose()
        {
        }

        #endregion

        /// <summary>
        /// Opens a session within a transaction at the beginning of the HTTP request.  Note that 
        /// it ONLY begins transactions for those designated as being transactional.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void BeginTransaction(object sender, EventArgs e)
        {
            // ReSharper disable PossibleNullReferenceException
            string requestFileExtension;
            try
            {
                requestFileExtension = Path.GetExtension(HttpContext.Current.Request.Path).ToLower();
            }
            catch (Exception)
            {

                return;
            }
            // ReSharper restore PossibleNullReferenceException
            requestFileExtension = string.IsNullOrEmpty(requestFileExtension) ? HttpContext.Current.Request.Path.ToLower() : requestFileExtension;
            if (requestFileExtension.Contains("aspx") || requestFileExtension.Contains("svc"))
            {
                var openSessionInViewSection = GetOpenSessionInViewSection();
                foreach (SessionFactoryElement sessionFactorySettings in openSessionInViewSection.SessionFactories)
                {
                    if (sessionFactorySettings.IsTransactional)
                        NHibernateSessionManager.Instance.BeginTransactionOn(
                            NHutils.GetHibernateConfigFileNameWithPath());
                }
            }
        }

        /// <summary>
        /// Commits and closes the NHibernate session provided by the supplied <see cref="NHibernateSessionManager"/>.
        /// Assumes a transaction was begun at the beginning of the request; but a transaction or session does
        /// not *have* to be opened for this to operate successfully.
        /// </summary>
        private static void CommitAndCloseSession(object sender, EventArgs e)
        {
            // ReSharper disable PossibleNullReferenceException
            string requestFileExtension;
            try
            {
                requestFileExtension = Path.GetExtension(HttpContext.Current.Request.Path).ToLower();
            }
            catch (Exception)
            {

                return;
            }
            // ReSharper restore PossibleNullReferenceException

            if (requestFileExtension.Contains("aspx") || requestFileExtension.Contains("svc"))
            {
                var openSessionInViewSection = GetOpenSessionInViewSection();

                try
                {
                    // Commit every session factory that's holding a transactional session
                    foreach (SessionFactoryElement sessionFactorySettings in openSessionInViewSection.SessionFactories)
                    {
                        if (sessionFactorySettings.IsTransactional)
                            NHibernateSessionManager.Instance.CommitTransactionOn(
                                NHutils.GetHibernateConfigFileNameWithPath());
                    }
                }
                finally
                {
                    // No matter what happens, make sure all the sessions get closed
                    foreach (SessionFactoryElement sessionFactorySettings in openSessionInViewSection.SessionFactories)
                    {
                        NHibernateSessionManager.Instance.CloseSessionOn(NHutils.GetHibernateConfigFileNameWithPath());
                    }
                }
            }

        }

        private static OpenSessionInViewSection GetOpenSessionInViewSection()
        {
            var openSessionInViewSection = ConfigurationManager
                                               .GetSection("nhibernateSettings") as OpenSessionInViewSection;

            Check.Ensure(openSessionInViewSection != null,
                         "The nhibernateSettings section was not found with ConfigurationManager.");
            return openSessionInViewSection;
        }
    }
}